/**
 * @file    system_GT98xx.c
 * @author  Giantec-Semi ATE
 * @brief   CMSIS Cortex-M4 Device Peripheral Access Layer System Source File
 * @version 0.1
 * 
 * @copyright Copyright (c) 2021 Giantec-Semi
 */

/**
 * @addtogroup CMSIS
 * @{
 */

/**
 * @addtogroup GT98xx_System
 * @{
 */

/**
 * @addtogroup GT98xx_System_Private_Includes
 * @{
 */

#include "gt98xx.h"

#if !defined  (HSE_VALUE) 
  #define HSE_VALUE    ((uint32_t)8000000) /*!< Default value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined  (HSI_VALUE)
  #define HSI_VALUE    ((uint32_t)8000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */

/** @} GT98xx_System_Private_Includes */

/**
 * @addtogroup GT98xx_System_Private_Variables
 * @{
 */
uint32_t SystemCoreClock = HSI_VALUE;
/** @} GT98xx_System_Private_Variables */

/**
 * @addtogroup GT98xx_System_Private_Functions
 * @{
 */

/**
 * @brief Setup the microcontroller system
 * 
 * @return None
 */
void SystemInit(void) {
  /* Configure Vector Table */
#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
  SCB->VTOR = (uint32_t)&(__VECTOR_TABLE[0]);
#endif

  /* Configure Vector Table */
#if defined (__FPU_USED) && (__FPU_USED == 1U)
  SCB->CPACR |= ((3UL << 10U * 2U) | (3UL << 11U * 2U));
#endif
}

/**
 * @brief Update SystemCoreClock variable
 * 
 * @return None
 */
void SystemCoreClockUpdate(void) {
  uint32_t tmp = 0, pll_m = 0, pll_n = 0, pll_od = 0,ahbdiv = 0;
  tmp = READ_BIT(CLK_CTL_REG->MCU_CLK_CFG,(MCU_CLK_CFG_SOURCE_LV2_1 | MCU_CLK_CFG_SOURCE_LV1_1 | MCU_CLK_CFG_SOURCE_LV1_2)) >> (MCU_CLK_CFG_SOURCE_LV2_1_Pos);
  switch (tmp) {
    case 0x00:
      SystemCoreClock = HSI_VALUE;
      break;
    case 0x02:
      SystemCoreClock = HSE_VALUE;
      break;
    case 0x01:
      pll_m = READ_BIT(CLK_CTL_REG->MCU_PLL_CFG,MCU_PLL_CFG_M) >> MCU_PLL_CFG_M_Pos;
      pll_n = READ_BIT(CLK_CTL_REG->MCU_PLL_CFG,MCU_PLL_CFG_N) >> MCU_PLL_CFG_N_Pos;
      pll_od = (READ_BIT(CLK_CTL_REG->MCU_PLL_CFG,MCU_PLL_CFG_OD) >> MCU_PLL_CFG_OD_Pos) + 1;
      if ((READ_BIT(CLK_CTL_REG->MCU_PLL_CFG,MCU_PLL_CFG_IN_SW) >> MCU_PLL_CFG_IN_SW_Pos) != 0) {
      SystemCoreClock = (pll_m/pll_n/pll_od)*(HSE_VALUE);
      }
      else {
      SystemCoreClock = (pll_m/pll_n/pll_od)*(HSI_VALUE);
      }
      break;
    case 0x05:
      pll_m = READ_BIT(CLK_CTL_REG->PWM_PLL_CFG,PWM_PLL_CFG_M) >> PWM_PLL_CFG_M_Pos;
      pll_n = READ_BIT(CLK_CTL_REG->PWM_PLL_CFG,PWM_PLL_CFG_N) >> PWM_PLL_CFG_N_Pos;
      pll_od = (READ_BIT(CLK_CTL_REG->PWM_PLL_CFG,PWM_PLL_CFG_OD) >> PWM_PLL_CFG_OD_Pos) + 1;
      if ((READ_BIT(CLK_CTL_REG->PWM_PLL_CFG,PWM_PLL_CFG_IN_SW) >> PWM_PLL_CFG_IN_SW_Pos) != 0) {
        SystemCoreClock = (pll_m/pll_n/pll_od)*(HSE_VALUE);
      }
      else {
        SystemCoreClock = (pll_m/pll_n/pll_od)*(HSI_VALUE);
      }
      break;
    default:
      SystemCoreClock = HSI_VALUE;
      break;
    }
    ahbdiv = (READ_BIT(CLK_CTL_REG->MCU_CLK_CFG,MCU_CLK_CFG_AHB_DIV) >> MCU_CLK_CFG_AHB_DIV_Pos);
    switch (ahbdiv)
    {
    case 00:
      SystemCoreClock >>= 0;
      break;
    case 01:
      SystemCoreClock >>= 1;
      break;
    case 03:
      SystemCoreClock >>= 2;
      break;
    case 07:
      SystemCoreClock >>= 3;
      break;
    case 15:
      SystemCoreClock >>= 4;
      break;
    default:
      SystemCoreClock >>= 1;
      break;
    }
}

/** @} GT98xx_System_Private_Functions */
/** @} GT98xx_System */
/** @} CMSIS */
